package com.gitee.dengmin.tenant.parser;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
import net.sf.jsqlparser.util.deparser.SelectDeParser;
import net.sf.jsqlparser.util.deparser.UpdateDeParser;

import java.util.List;

public class SQLParser {

    protected static class SQLParserSelect extends SelectDeParser{
        private String schemaName;

        public SQLParserSelect(ExpressionVisitor expressionVisitor, StringBuilder buffer) {
            super(expressionVisitor, buffer);
        }

        public String getSchemaName() {
            return schemaName;
        }

        public void setSchemaName(String schemaName) {
            this.schemaName = schemaName;
        }

        @Override
        public void visit(Table tableName) {
            tableName.setSchemaName(schemaName);
            StringBuilder buffer = getBuffer();
            buffer.append(tableName.getFullyQualifiedName());
            Pivot pivot = tableName.getPivot();
            if (pivot != null) {
                pivot.accept(this);
            }
            Alias alias = tableName.getAlias();
            if (alias != null) {
                buffer.append(alias);
            }
        }
    }

    public static String doSelect(Select select, String schemaName){
        StringBuilder buffer = new StringBuilder();
        ExpressionDeParser expressionDeParser = new ExpressionDeParser();
        SQLParserSelect parser = new SQLParserSelect(expressionDeParser, buffer);
        parser.setSchemaName(schemaName);
        expressionDeParser.setSelectVisitor(parser);
        expressionDeParser.setBuffer(buffer);
        select.getSelectBody().accept(parser);
        return buffer.toString();
    }

    public static String doInsert(Insert insert, String schemaName){
        StringBuilder buffer = new StringBuilder();
        Table t = insert.getTable();
        t.setSchemaName(schemaName);
        insert.setTable(t);
        Select select = insert.getSelect();
        if (select != null) {
            ExpressionDeParser expressionDeParser = new ExpressionDeParser();
            SQLParserSelect _parser = new SQLParserSelect(expressionDeParser, buffer);
            _parser.setSchemaName(schemaName);
            expressionDeParser.setSelectVisitor(_parser);
            expressionDeParser.setBuffer(buffer);
            select.getSelectBody().accept(_parser);
            insert.setSelect(select);
        }
        return insert.toString();
    }


    public static String doUpdate(Update update, String schemaName) throws JSQLParserException{
        StringBuilder buffer = new StringBuilder();
        Table tb = update.getTable();
        tb.setSchemaName(schemaName);
        update.setTable(tb);
        // 处理from
        FromItem fromItem = update.getFromItem();
        if (fromItem != null) {
            Table tf = (Table) fromItem;
            tf.setSchemaName(schemaName);
        }
        // 处理join
        List<Join> joins = update.getJoins();
        if (joins != null && joins.size() > 0) {
            for (Object object : joins) {
                Join t = (Join) object;
                Table rightItem = (Table) t.getRightItem();
                rightItem.setSchemaName(schemaName);
                System.out.println();
            }
        }
        ExpressionDeParser expressionDeParser = new ExpressionDeParser();
        UpdateDeParser p = new UpdateDeParser(expressionDeParser, null, buffer);
        expressionDeParser.setBuffer(buffer);
        p.deParse(update);

        Expression where = update.getWhere();
        if(where != null){
            InExpression getRightItems = (InExpression) where;
            ItemsList rightItemsList = getRightItems.getRightItemsList();
            if (rightItemsList instanceof SubSelect) {
                SubSelect s = (SubSelect) rightItemsList;
                SelectBody selectBody = s.getSelectBody();
                Select se = (Select) CCJSqlParserUtil.parse(selectBody.toString());

                StringBuilder bf = new StringBuilder();
                ExpressionDeParser exp = new ExpressionDeParser();
                SQLParserSelect _parser = new SQLParserSelect(exp, bf);
                _parser.setSchemaName(schemaName);
                expressionDeParser.setSelectVisitor(_parser);
                expressionDeParser.setBuffer(bf);
                se.getSelectBody().accept(_parser);
                s.setSelectBody(se.getSelectBody());
            }
        }

        return update.toString();
    }


    public static String doDelete(Delete delete, String schemaName) throws JSQLParserException{
        Table t = delete.getTable();
        t.setSchemaName(schemaName);
        delete.setTable(t);
        Expression where = delete.getWhere();
        if (where != null) {
            InExpression getRightItems = (InExpression) where;
            ItemsList rightItemsList = getRightItems.getRightItemsList();
            if (rightItemsList instanceof SubSelect) {
                SubSelect s = (SubSelect) rightItemsList;
                SelectBody selectBody = s.getSelectBody();
                Select se = (Select) CCJSqlParserUtil.parse(selectBody.toString());

                StringBuilder buffer = new StringBuilder();
                ExpressionDeParser expressionDeParser = new ExpressionDeParser();
                SQLParserSelect _parser = new SQLParserSelect(expressionDeParser, buffer);
                _parser.setSchemaName(schemaName);
                expressionDeParser.setSelectVisitor(_parser);
                expressionDeParser.setBuffer(buffer);
                se.getSelectBody().accept(_parser);
                s.setSelectBody(se.getSelectBody());
            }
        }
        return delete.toString();
    }

    public static void main(String[] args) throws JSQLParserException {
        String insert = SQLParser.doInsert((Insert) CCJSqlParserUtil.parse("Insert into article select  *  from bank"), "`member`");
        System.out.println(insert);
        String delete = SQLParser.doDelete((Delete)CCJSqlParserUtil.parse("delete from cap where id in (select p.user_id from per p left join test a on(a.id = b.id) inner join test t on(p.id = t.id) where t=1)"),"`rose`");
        System.out.println(delete);
        String txt = "SELECT o.* FROM unifiedorderclearing AS o\n" +
                "        LEFT JOIN unifiedorderclearingitem AS oi ON oi.orderId = o.id\n" +
                "        LEFT JOIN unifiedOrder as ou ON ou.id=o.orderId\n" +
                "        where 1=1 and o.username='test'";
        String select = SQLParser.doSelect((Select)CCJSqlParserUtil.parse(txt), "`eth`");
        System.out.println(select);

        String update = SQLParser.doUpdate((Update)CCJSqlParserUtil.parse("update cart set a=1, b=new() where id in (select p.user_id from per p left join test a on(a.id = b.id) inner join test t on(p.id = t.id) where t=1)"), "`rose`");
        System.out.println(update);

    }
}
